const redis = require('redis');
const redisConfig = require('../config/redis.config');

// 创建Redis客户端
let redisClient;
let redisEnabled = true;
let reconnectAttempts = 0;
const MAX_RECONNECT_ATTEMPTS = 3;

try {
  redisClient = redis.createClient({
    url: redisConfig.url,
    ...redisConfig.options
  });

  // 连接Redis
  (async () => {
    try {
      await redisClient.connect();
      
      // 选择指定的数据库
      if (redisConfig.database !== 0) {
        await redisClient.select(redisConfig.database);
        console.log(`Redis缓存服务选择数据库: ${redisConfig.database}`);
      }
      
      console.log('Redis缓存服务连接成功');
      
      // 添加重连成功的处理
      redisClient.on('connect', () => {
        console.log('Redis缓存服务重新连接成功');
        redisEnabled = true;
        reconnectAttempts = 0;
        
        // 重新连接后需要重新选择数据库
        (async () => {
          try {
            if (redisClient.isReady && redisConfig.database !== 0) {
              await redisClient.select(redisConfig.database);
            }
          } catch (err) {
            console.error('Redis重连后选择数据库失败:', err.message);
          }
        })();
      });
    } catch (err) {
      console.error('Redis缓存服务连接失败:', err.message);
      redisEnabled = false;
    }
  })();

  // 监听Redis连接错误
  redisClient.on('error', (err) => {
    console.error('Redis缓存服务连接错误:', err.message);
    redisEnabled = false;
  });
  
  // 监听断开连接事件
  redisClient.on('end', () => {
    console.log('Redis缓存服务连接已断开');
    redisEnabled = false;
  });
} catch (err) {
  console.error('Redis客户端创建失败:', err.message);
  redisEnabled = false;
}

/**
 * 缓存服务
 * 提供Redis缓存功能，用于提高API性能
 * 当Redis不可用时，将直接调用原始函数
 */
class CacheService {
  /**
   * 设置缓存
   * @param {string} key - 缓存键
   * @param {any} value - 缓存值
   * @param {number} expireTime - 过期时间（秒）
   * @returns {Promise<string>} 操作结果
   */
  async set(key, value, expireTime = 3600) {
    if (!redisEnabled || !redisClient.isReady) return null;

    try {
      // 将对象转换为JSON字符串
      const stringValue = typeof value === 'object' ? JSON.stringify(value) : String(value);
      
      // 设置缓存并设置过期时间
      return await redisClient.set(key, stringValue, {
        EX: expireTime
      });
    } catch (error) {
      console.error('缓存设置失败:', error.message);
      return null;
    }
  }

  /**
   * 获取缓存
   * @param {string} key - 缓存键
   * @returns {Promise<any>} 缓存值
   */
  async get(key) {
    if (!redisEnabled || !redisClient.isReady) return null;

    try {
      const value = await redisClient.get(key);
      
      if (!value) return null;
      
      // 尝试将JSON字符串转换回对象
      try {
        return JSON.parse(value);
      } catch (e) {
        // 如果不是有效的JSON，则返回原始值
        return value;
      }
    } catch (error) {
      return null;
    }
  }

  /**
   * 删除缓存
   * @param {string} key - 缓存键
   * @returns {Promise<number>} 删除的键数量
   */
  async del(key) {
    if (!redisEnabled || !redisClient.isReady) return 0;

    try {
      return await redisClient.del(key);
    } catch (error) {
      return 0;
    }
  }

  /**
   * 清除匹配模式的所有缓存
   * @param {string} pattern - 匹配模式
   * @returns {Promise<number>} 删除的键数量
   */
  async delByPattern(pattern) {
    if (!redisEnabled || !redisClient.isReady) return 0;

    try {
      // 查找匹配的键
      const keys = await redisClient.keys(pattern);
      
      if (keys.length === 0) return 0;
      
      // 删除所有匹配的键
      return await redisClient.del(keys);
    } catch (error) {
      return 0;
    }
  }

  /**
   * 检查键是否存在
   * @param {string} key - 缓存键
   * @returns {Promise<boolean>} 是否存在
   */
  async exists(key) {
    if (!redisEnabled || !redisClient.isReady) return false;

    try {
      return (await redisClient.exists(key)) === 1;
    } catch (error) {
      return false;
    }
  }

  /**
   * 设置缓存过期时间
   * @param {string} key - 缓存键
   * @param {number} seconds - 过期时间（秒）
   * @returns {Promise<boolean>} 操作结果
   */
  async expire(key, seconds) {
    if (!redisEnabled || !redisClient.isReady) return false;

    try {
      return (await redisClient.expire(key, seconds)) === 1;
    } catch (error) {
      return false;
    }
  }

  /**
   * 获取缓存或从回调函数获取并缓存
   * @param {string} key - 缓存键
   * @param {Function} callback - 回调函数，用于获取数据
   * @param {number} expireTime - 过期时间（秒）
   * @returns {Promise<any>} 数据
   */
  async getOrSet(key, callback, expireTime = 3600) {
    if (!redisEnabled || !redisClient.isReady) {
      // 如果Redis不可用，直接调用回调函数
      return await callback();
    }

    try {
      // 尝试从缓存获取
      const cachedValue = await this.get(key);
      
      // 如果缓存存在，直接返回
      if (cachedValue !== null) {
        return cachedValue;
      }
      
      // 否则，调用回调函数获取数据
      const freshValue = await callback();
      
      // 将新数据存入缓存
      if (freshValue !== null && freshValue !== undefined) {
        await this.set(key, freshValue, expireTime);
      }
      
      return freshValue;
    } catch (error) {
      // 出错时尝试直接调用回调函数
      return await callback();
    }
  }
}

module.exports = new CacheService();